/*
 * Copyright 2010 Chad Retz
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.jdocng.shared.model;

import java.lang.reflect.Modifier;

import javax.xml.bind.annotation.XmlType;

import com.google.common.annotations.GwtCompatible;
import com.google.gson.annotations.Expose;
import com.sun.javadoc.ProgramElementDoc;

/**
 * Implementation of {@link ProgramElementDoc}
 *
 * @author Chad Retz
 */
@XmlType(name = "programElement")
@GwtCompatible(serializable = true)
@SuppressWarnings("serial")
public abstract class ProgramElementDocImpl extends DocImpl implements ProgramElementDoc {

    //exposed fields
    
    @Expose
    private AnnotationDescImpl[] annotations;
    
    @Expose
    private String containingClass;
    
    @Expose
    private String containingPackage;
    
    @Expose
    private int modifierSpecifier;
    
    @Expose
    private String qualifiedName;
    
    //non-exposed fields
    
    private transient ClassDocImpl containingClassLoaded;
    
    private transient PackageDocImpl containingPackageLoaded;
    
    //ProgramElementDoc interface impl
    
    @Override
    public AnnotationDescImpl[] annotations() {
        return annotations;
    }
    
    @Override
    public ClassDocImpl containingClass() {
        if (containingClass == null) {
            return null;
        }
        if (containingClassLoaded == null) {
            containingClassLoaded = getContext().getClassDoc(containingClass);
        }
        return containingClassLoaded;
    }
    
    @Override
    public PackageDocImpl containingPackage() {
        if (containingPackageLoaded == null) {
            containingPackageLoaded = getContext().
                    getPackageDoc(containingPackage);
        }
        return containingPackageLoaded;
    }
    
    @Override
    public boolean isFinal() {
        return Modifier.isFinal(modifierSpecifier);
    }
    
    @Override
    public boolean isPackagePrivate() {
        return !isPublic() && !isPrivate() && !isProtected(); 
    }
    
    @Override
    public boolean isPrivate() {
        return Modifier.isPrivate(modifierSpecifier);
    }
    
    @Override
    public boolean isProtected() {
        return Modifier.isProtected(modifierSpecifier);
    }
    
    @Override
    public boolean isPublic() {
        return Modifier.isPublic(modifierSpecifier);
    }
    
    @Override
    public boolean isStatic() {
        return Modifier.isStatic(modifierSpecifier);
    }
    
    @Override
    public String modifiers() {
        return Modifier.toString(modifierSpecifier);
    }
    
    @Override
    public int modifierSpecifier() {
        return modifierSpecifier;
    }
    
    @Override
    public String qualifiedName() {
        return qualifiedName;
    }
    
    //other accessors
    
    public void setAnnotations(AnnotationDescImpl[] annotations) {
        this.annotations = annotations;
    }
    
    public String getContainingClass() {
        return containingClass;
    }
    
    public void setContainingClass(String containingClass) {
        this.containingClass = containingClass;
    }
    
    public String getContainingPackage() {
        return containingPackage;
    }
    
    public void setContainingPackage(String containingPackage) {
        this.containingPackage = containingPackage;
    }
    
    public void setModifierSpecifier(int modifierSpecifier) {
        this.modifierSpecifier = modifierSpecifier;
    }
    
    public void setQualifiedName(String qualifiedName) {
        this.qualifiedName = qualifiedName;
    }
    
}
